#ifndef MY_UTILS_H__
#define MY_UTILS_H__

#ifdef __cplusplus
extern "C" {
#endif

#include <stdlib.h>
#include <string.h>
#include "stdint.h"
#include "stdbool.h"
#include <time.h>

void *memcpy_safe(void *dst, const void *src, uint32_t count, uint32_t max_len);
char * strstr_safe ( const char * s1, const char * s2, uint32_t max_len );

void * memset_safe ( void * s, int c, uint32_t count, uint32_t max_len );
void * memclear ( void * s, uint32_t count );

#ifdef __GNUC__
// 更安全版, max_len必须为常数
#define MEMSET_S(s, c, count, max_len)  \
do{     \
    PT_ASSERT(__builtin_constant_p(max_len));   \
    memset_safe(s, c, count, max_len);      \
}while(0)

#define MEMCPY_S(dst, src, count, max_len)  \
do{     \
    PT_ASSERT(__builtin_constant_p(max_len));   \
    memcpy_safe(dst, src, count, max_len);      \
}while(0)

#define STRSTR_S(s1, s2, max_len)  \
do{     \
    PT_ASSERT(__builtin_constant_p(max_len));   \
    strstr_safe(dst, src, max_len);      \
}while(0)

#endif // __GNUC__


unsigned char AscToHex ( char h, char l );

uint32_t reverse_byte(uint32_t val, uint8_t num);

bool DATE_TIME_to_tm(struct tm *p_tm);

/**
 * container_of - return the member address of ptr, if the type of ptr is the
 * struct type.
 */
#ifndef container_of
#define container_of(ptr, type, member) \
    ((type *)((char *)(ptr) - (unsigned long)(&((type *)0)->member)))
#endif // container_of

#ifdef __PT_CONFIG_H__
#define my_malloc   pt_malloc
#define my_free     pt_free
#else
#define my_malloc   malloc
#define my_free     free
#endif

#define new_obj(type, init_func, release_func, ptr)     \
do{                             \
    ptr = my_malloc(sizeof(type) );    \
    if (ptr != (void *)0 ){     \
        ptr->init = init_func;  \
        ptr->release = release_func;  \
        if ( ptr->init != (void *)0 ){  \
            ptr->init(ptr);        \
        }                           \
    }                              \
}while(0)

#define new_obj(type, init_func, release_func, ptr)     \
do{                             \
    ptr = my_malloc(sizeof(type) );    \
    if (ptr != (void *)0 ){     \
        ptr->init = init_func;  \
        ptr->release = release_func;  \
        if ( ptr->init != (void *)0 ){  \
            ptr->init(ptr);        \
        }                           \
    }                              \
}while(0)

#define del_obj(ptr)     \
do{                             \
    if (ptr != (void *)0 ){     \
       if(ptr->release != (void *)0 ){  \
            ptr->release(ptr);          \
       }                \
       my_free(ptr);       \
       ptr = (void *)0;         \
    }                              \
}while(0)

// 测试位
static inline bool test_bit(uint32_t num, uint32_t bit_cnt)
{
	if(num & (1 << bit_cnt) ){
		return true;
	}

	return false;

}


//================= 栈操作 ========================
#define STACK_STATUS_OK     0X0000
#define STACK_FULL          0X00A0
#define STACK_EMPTY         0X00B0
typedef struct{
    int32_t element_cnt;    // 栈元素个数
    int32_t stack_size;     // 栈大小
    int32_t element_size;   // 栈元素大小
    uint8_t contents[];     // 栈缓存区内存

}stack_t;

void stack_make_empty(stack_t *s);
bool stack_is_empty(const stack_t *s);
bool stack_is_full(const stack_t *s);
int32_t stack_push(stack_t *s, void *in);
int32_t stack_pop(stack_t *s, void *out);
stack_t *stack_create(int32_t stack_size, int32_t element_size);

#define DEFINE_STACK(name, element_max, element_size)    \
struct stack_and_buf{               \
    stack_t     stack_ins;          \
    uint8_t     buf[element_max * element_size];    \
};  \
struct stack_and_buf name##_whole = { \
    { 0, element_max * element_size, element_size }   \
};\
stack_t *name = &name##_whole.stack_ins;


//================= 栈操作 end ========================

// 获取数组元素个数
#ifndef SIZEOF_ARR
    #define SIZEOF_ARR(arr)     ( (int32_t)( sizeof(arr) / sizeof(arr[0]) ) )
#endif

#ifdef __GNUC__
#define MAX(x, y) ({            \
    __typeof(x) _x = x;         \
    __typeof(y) _y = y;         \
    (void) ( &_x == &_y );      \
    _x >_y ? _x : _y;           \
})
#else
#define MAX(x,y)     ( (x) > (y)?(x):(y) )
#endif // __GNUC__



#ifdef __cplusplus
}
#endif

#endif // MY_UTILS_H__

